package loading.services;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import javax.servlet.http.*;

@SuppressWarnings("serial")
public class Services extends HttpServlet {
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		
		String function = req.getParameter("function");
		
		// function=pay
		if(function.equals("pay")){
			String merchantId = req.getParameter("merchantId");
			double amount = Double.parseDouble(req.getParameter("amount"));
			String scheme = req.getParameter("scheme");
			
			HttpSession session = req.getSession();
			String consumerId = (String) session.getAttribute("consumerId");
			payMerchant(merchantId, consumerId, amount, scheme);
		}
		
		// function=getbalance
		else if(function.equals("getbalance")){
			String kind = req.getParameter("kind");
			String id = null;
			if(kind.equals("Consumer")){
				HttpSession session = req.getSession();
				id = (String) session.getAttribute("consumerId");
			}else if(kind.equals("Merchant")){
				id = req.getParameter("merchantId");
			}
			resp.setContentType("application/json");
			resp.getWriter().print("{\"balance\": " + getBalance(kind, id) + ", \"fundsource\": \""+getFundSource(kind, id)+"\"}");
		}
		
		// function=getschemebalance
		else if(function.equals("getschemebalance")){
			HttpSession session = req.getSession();
			String id = (String) session.getAttribute("consumerId");
			
			DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
			Key key = KeyFactory.createKey("Consumer", id);
			Entity consumer = null;
			try {
				consumer = datastore.get(key);
			} catch (EntityNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			String scheme = (String) consumer.getProperty("scheme");
			double schemebalance = (Double) consumer.getProperty("schemebalance");
			
			resp.setContentType("application/json");
			String json;
			if(scheme.equals("") || schemebalance == 0){
				json = "{\"scheme\": null}";
			}else{
				json = "{\"scheme\": \"" + scheme + "\", \"schemebalance\": "+schemebalance+"}";
			}
			resp.getWriter().print(json);
		}
		
		// function=gethistory
		else if(function.equals("gethistory")){
			String kind = req.getParameter("kind");
			String id = null;
			if(kind.equals("Consumer")){
				HttpSession session = req.getSession();
				id = (String) session.getAttribute("consumerId");
			}else if(kind.equals("Merchant")){
				id = req.getParameter("merchantId");
			}
			resp.setContentType("application/json");
			resp.getWriter().print("[" + getHistory(kind, id) + "]");
		}
		
		// function=fundscheme
		else if(function.equals("fundscheme")){
			String scheme = req.getParameter("scheme");
			double amount = Double.parseDouble(req.getParameter("amount"));
			
			HttpSession session = req.getSession();
			String consumerId = (String) session.getAttribute("consumerId");
			fundScheme(scheme, amount, consumerId);
			
			resp.setContentType("application/json");
			resp.getWriter().print("{\"balance\": \""+getBalance("Consumer", consumerId)+"\", \"fundsource\": \""+getFundSource("Consumer", consumerId)+"\", ");
			resp.getWriter().print("\"scheme\": \""+scheme+"\", \"schemebalance\": \""+amount+"\"}");
		}
		
	}
	
	private void payMerchant(String merchantId, String consumerId, double amount, String scheme)
	{
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Key mKey = KeyFactory.createKey("Merchant", merchantId);
		Key cKey = KeyFactory.createKey("Consumer", consumerId);
		
		Entity merchant = null;
		Entity consumer = null;
		try {
			merchant = datastore.get(mKey);
			consumer = datastore.get(cKey);
		} catch (EntityNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		double mPrevAmount = (Double) merchant.getProperty("balance");
		merchant.setProperty("balance", mPrevAmount + amount);
		
		if(scheme != null){
			double cPrevAmount = (Double) consumer.getProperty("schemebalance");
			consumer.setProperty("schemebalance", cPrevAmount - amount);
		}else{
			double cPrevAmount = (Double) consumer.getProperty("balance");
			consumer.setProperty("balance", cPrevAmount - amount);
		}
		
		String to = "to";
		String from = "from";
		addHistoryItem(consumer, merchant, amount, from, scheme);
		addHistoryItem(merchant, consumer, amount, to, scheme);
		
		datastore.put(merchant);
		datastore.put(consumer);
	}
	
	private void addHistoryItem(Entity from, Entity to, double amount, String toFrom, String scheme)
	{
		String txnId = "T" + String.valueOf(Math.round(Math.random() * 100000)); 
		String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime());
		String historyItem = "{\"txnid\": \""+txnId+"\" , \"timestamp\": \"" + timestamp + "\", \"amount\": " + amount + ", \""+ toFrom +"\": \"" 
				+ from.getProperty("username") + "\"";
		
		String jsonEnd;
		if(scheme != null){
			jsonEnd = ", \"scheme\": " + "\""+ scheme +"\"}";
		}else{
			jsonEnd = "}";
		}
		historyItem += jsonEnd;
		
		String history = (String) to.getProperty("history");
		if(history.equals("")){
			history = historyItem;
		}else{
			history += "," + historyItem;
		}
		to.setProperty("history", history);
	}
	
	private double getBalance(String kind, String id)
	{
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Key key = KeyFactory.createKey(kind, id);
		Entity user = null;
		try {
			user = datastore.get(key);
		} catch (EntityNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return (Double) user.getProperty("balance");
	}
	
	private String getFundSource(String kind, String id)
	{
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Key key = KeyFactory.createKey(kind, id);
		Entity user = null;
		try {
			user = datastore.get(key);
		} catch (EntityNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return (String) user.getProperty("fundsource");
	}
	
	private String getHistory(String kind, String id)
	{
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Key key = KeyFactory.createKey(kind, id);
		Entity user = null;
		try {
			user = datastore.get(key);
		} catch (EntityNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return (String) user.getProperty("history");
	}
	
	private void fundScheme(String schemeName, double amount, String consumerId)
	{
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Key key = KeyFactory.createKey("Consumer", consumerId);
		Entity consumer = null;
		try {
			consumer = datastore.get(key);
		} catch (EntityNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		consumer.setProperty("scheme", schemeName);
		consumer.setProperty("schemebalance", amount);
		
		double prevAmount = (Double) consumer.getProperty("balance");
		
		consumer.setProperty("balance", prevAmount - amount);
		datastore.put(consumer);
	}
}
